#pragma once
#include "elisa/elisa.h"
#include <iostream>
#include <sstream>
#include <algorithm>
#include <string>
#include <vector>
#include <gaol/gaol>

#include "Modeler.h"

#ifdef ELISA_PERFORMER
#include "elisa_chrono.h"
#endif

using namespace std;
using namespace elisa;

class Floudas : public Modeler
{
private:
	Model _model;

	RealVar x1;
	RealVar x2;
	RealVar x3;
	RealVar x4;
	RealVar x5;
	RealVar x6;
	RealVar x7;
	RealVar x8;
	RealConstraint c1;
	RealConstraint c2;
	RealConstraint c3;
	RealConstraint c4;
	RealConstraint c5;
	RealConstraint c6;
	RealConstraint c7;
	RealConstraint c8;

public:
	Floudas()
		: x1(Interval(-1,1), "x1"),
		  x2(Interval(-1,1), "x2"),
		  x3(Interval(-1,1), "x3"),
		  x4(Interval(-1,1), "x4"),
		  x5(Interval(-1,1), "x5"),
		  x6(Interval(-1,1), "x6"),
		  x7(Interval(-1,1), "x7"),
		  x8(Interval(-1,1), "x8"),
		  c1(4.731e-03*x1*x2 - 0.3578*x2*x3 - 0.1238*x1 +x7 - 1.637e-03*x2 - 0.9338*x4 - 0.3571 == 0),
		  c2(0.2238*x1*x3 + 0.7623*x2*x3 + 0.2638*x1 -x7 - 0.07745*x2 - 0.6734*x4 - 0.6022 == 0),
		  c3(x6*x8 + 0.3578*x1 + 4.731e-03*x2 == 0),
		  c4(-0.7623*x1 + 0.2238*x2 + 0.3461 == 0),
		  c5(pow(x1,2) +pow(x2,2) == 1),
		  c6(pow(x3,2) +pow(x4,2) == 1),
		  c7(pow(x5,2) +pow(x6,2) == 1),
		  c8(pow(x7,2) +pow(x8,2) == 1),
		  _model()
	{
	}

	elisa::Model & model()
	{
		_model = c1 && c2 && c3 && c4 && c5 && c6 && c7 && c8;
		return _model;
	}

	void print()
	{
		cout << '\t' << x1.getName() << " = " << x1.domain() << endl;
		cout << '\t' << x2.getName() << " = " << x2.domain() << endl;
		cout << '\t' << x3.getName() << " = " << x3.domain() << endl;
		cout << '\t' << x4.getName() << " = " << x4.domain() << endl;
		cout << '\t' << x5.getName() << " = " << x5.domain() << endl;
		cout << '\t' << x6.getName() << " = " << x6.domain() << endl;
		cout << '\t' << x7.getName() << " = " << x7.domain() << endl;
		cout << '\t' << x8.getName() << " = " << x8.domain() << endl;
	}

	RealVar & varX()
	{
		return x1;
	}
	RealVar & varY()
	{
		return x2;
	}
};
